<!--
 * @description: 已选实体列表(实例)
 * @fileName: SelectedList.vue
 * @author: ssr
 * @date: 2023-01-05 15:05:47
 * @version: V1.0.0
! -->
<script setup lang="ts">
import type {
  ICampItem,
  IControlInstance,
  IControlItem,
  IEntityInstance,
  Position
} from "@@/apis/scn/type"
import type { CustomViewer, IDrawCallback } from "@@/utils/CustomCesium/CustomCesium"
import type { Cartesian3 } from "cesium"
import type { TabsPaneContext } from "element-plus"

import { useCesiumStore } from "@/pinia/stores/cesium"
import { useScenarioStore } from "@/pinia/stores/scenario"
import {
  deleteControlInstance,
  deleteEntityInstance,
  getCampList,
  getSelectedEntityObjectsByScn,
  getSelectedInstanceByScnId,
  updateControlObjPath,
  updateEntityPosition
} from "@@/apis/scn"
import { ControlObjectMap, FormTypeEnum } from "@@/constants/other-keys"
import { MathUtils } from "@@/utils/CustomCesium/CustomCesium"
import mitter from "@@/utils/mitter"
import { Close, Edit, MoreFilled, Plus, Rank } from "@element-plus/icons-vue"
import { ElMessage, ElMessageBox } from "element-plus"
import { cloneDeep, isEmpty } from "lodash-es"
import { computed, onActivated, onMounted, reactive, ref, toRefs, watch } from "vue"
import DescriptionDialog from "./DescriptionDialog.vue"
import EditCampDialog from "./EditCampDialog.vue"
import WeaponMountDialog from "./WeaponMountDialog.vue"

// 获取状态
const route = useRoute()
const scnId = ref(route.query.id as string)
const scenarioStore = useScenarioStore()
const cesiumStore = useCesiumStore()

// 引用
const WeaponMountDialogRef = ref()
const DescriptionDialogRef = ref()
const EditCampDialogRef = ref()

// 状态数据
const state = reactive({
  // 阵营列表
  campList: [] as ICampItem[],
  // 阵营ID
  campId: "all",
  // 实体列表
  list: [] as IEntityInstance[],
  // 显示列表
  showList: [] as IEntityInstance[],
  // 控制对象列表
  controlList: [] as IControlInstance[],
  // 显示控制对象列表
  showControlList: [] as IControlInstance[],
  // 加载状态
  loading: false,
  // 当前选中ID
  currentId: "",
  // 当前选中实体模板id
  currentTempId: "",
  // 对话框类型
  dialogType: FormTypeEnum.CREATE,
  // 当前激活的标签页
  activeKey: "instance"
})

// 解构状态
const {
  campList,
  campId,
  showList,
  showControlList,
  currentId,
  currentTempId,
  dialogType,
  activeKey
} = toRefs(state)

// 已选列表面板显示控制
const selectedListShow = computed(() => {
  return !scenarioStore.selectedListShow
})

/**
 * 关闭已选列表面板
 */
function handleClose() {
  scenarioStore.setSelectedListShow(!scenarioStore.selectedListShow)
}

/**
 * 切换阵营
 */
function handleChangeCamp(value: string) {
  let camp = state.campList.find(item => item.id === value)
  state.campId = value
  if (isEmpty(camp)) {
    scenarioStore.currentSide = null
  } else {
    scenarioStore.currentSide = camp
  }
  handleSearchEntity()
  handleSearchControlList()
}

/**
 * 切换标签页
 */
function handleTabChange(tab: TabsPaneContext) {
  if (tab.props.name === "instance") {
    handleSearchEntity()
  }
  if (tab.props.name === "controlObject") {
    handleSearchControlList()
  }
  state.activeKey = tab.props.name
}

/**
 * 编辑实体
 */
function handleEntityEdit(item: IEntityInstance) {
  state.currentId = item.id
  mitter.emit("EntityEditDialogShow", item.id)
}

/**
 * 删除实体
 */
function handleEntityDelete(item: IEntityInstance) {
  ElMessageBox.confirm(
    `确定要删除实体 ${item.basicInfo.entityName} 吗？`,
    "删除确认",
    {
      confirmButtonText: "确定",
      cancelButtonText: "取消",
      type: "warning"
    }
  )
    .then(() => {
      const index = scenarioStore.getEntityInstanceById(item.id)
      const instance = scenarioStore.selectedEntityList[index]
      deleteEntityInstance(item.id)
        .then(() => {
          ElMessage.success("删除成功")
          handleSearchEntity()
          // 更新场景
          scenarioStore.drawEntityManager?.clearById(instance.cesiumId)
        })
        .catch(() => {
          ElMessage.error("删除失败")
        })
    })
    .catch(() => {
      // 用户取消删除
    })
}

/**
 * 编辑实体位置
 */
function handleInstanceEditVertex(item: IEntityInstance) {
  if (!cesiumStore.customViewer) return

  const index = scenarioStore.getEntityInstanceById(item.id)
  const instance: IEntityInstance
            = scenarioStore.selectedEntityList[index]
  const editManager = scenarioStore.drawEntityManager

  const callback = (res: IDrawCallback) => {
    // 更新顶点坐标
    const positions: Position[] = handleParsePosition(
      res.position
    )

    if (positions) {
      updateEntityPosition({
        id: instance.id,
        position: positions[0]
      })
        .then(() => {
          instance.basicInfo = Object.assign(
            instance.basicInfo,
            positions[0]
          )
          instance.cesiumPosition = res.position[0]
          scenarioStore.selectedEntityList.splice(index, 1, instance)
          // 更新左侧列表数据
          mitter.emit("updateSelectedEntity")
        })
        .catch(() => {
          ElMessage.error("更新位置失败")
        })
    }
  }

  instance.cesiumId && editManager?.editDrawEntity(instance.cesiumId, instance.cesiumPosition, callback)
}

// cesium坐标转换
function handleParsePosition(
  cesiumPosition: Cartesian3 | Cartesian3[]
): Position[] {
  let positions: Position[] = []
  if (cesiumStore.customViewer) {
    if (!Array.isArray(cesiumPosition)) {
      // 对象
      positions.push(
        MathUtils.car3ToGCS(
          cesiumStore.customViewer.viewer,
          cesiumPosition
        )
      )
    } else {
      // 数组
      cesiumPosition.forEach((pos) => {
        cesiumStore.customViewer
        && positions.push(
          MathUtils.car3ToGCS(cesiumStore.customViewer.viewer, pos)
        )
      })
    }
  }
  return positions
}

/**
 * 编辑控制对象
 */
function handleControlEdit(item: IControlItem) {
  scenarioStore.setCurrentControlObj(item)
  mitter.emit("control-edit", item.id)
}

/**
 * 编辑控制对象顶点
 */
function handleControlEditVertex(item: IControlItem) {
  if (!cesiumStore.customViewer) return

  const index = scenarioStore.getControlInstanceById(item.id)
  const instance: IControlInstance
            = scenarioStore.selectedObjList[index]
  const drawingManager = cesiumStore.customViewer?.drawingManager

  const callback = (res: IDrawCallback) => {
    // 更新顶点坐标
    const positions: Position[] = handleParsePosition(
      res.position
    )

    if (positions) {
      updateControlObjPath({ id: instance.id, path: JSON.stringify(positions) }).then(() => {
        instance.positions = positions
        instance.path = JSON.stringify(positions)
        instance.cesiumPosition = res.position
        scenarioStore.selectedObjList.splice(index, 1, instance)
      }).catch(() => {
        // 保存失败 回复原样
        instance.cesiumId
        && drawingManager
        && drawingManager.updateActiveEntity(
          drawingManager.getById(instance.cesiumId),
          instance.type,
          instance.cesiumPosition,
          false
        )
        drawingManager && drawingManager.resetMarkPoints(
          instance.cesiumId,
          instance.type,
          instance.cesiumPosition
        )
      })
    }
  }
  instance.cesiumId
  && drawingManager
  && drawingManager.editDraw(instance.cesiumId, item.type, instance.cesiumPosition, callback)
}

/**
 * 删除控制对象
 */
function handleControlDelete(item: IControlItem) {
  ElMessageBox.confirm(
    `确定要删除控制对象 ${item.name} 吗？`,
    "删除确认",
    {
      confirmButtonText: "确定",
      cancelButtonText: "取消",
      type: "warning"
    }
  )
    .then(() => {
      deleteControlInstance(item.id)
        .then(() => {
          ElMessage.success("删除成功")
          handleSearchControlList()
          // 更新场景
          cesiumStore.customViewer?.removeControl(item.id)
        })
        .catch(() => {
          ElMessage.error("删除失败")
        })
    })
    .catch(() => {
      // 用户取消删除
    })
}

/**
 * 新增阵营
 */
function handleAddCamp() {
  state.dialogType = FormTypeEnum.CREATE
  EditCampDialogRef.value.handleShowDialog()
}

/**
 * 编辑阵营
 */
function handlEditCamp() {
  if (state.campId === "all") {
    ElMessage.warning("请选择要编辑的阵营")
    return
  }
  nextTick(() => {
    state.dialogType = FormTypeEnum.EDIT
    EditCampDialogRef.value.handleShowDialog()
  })
}

/**
 * 更新阵营列表
 */
function uplateCampList() {
  handleSearchCampList()
}

/**
 * 显示武器挂载对话框
 */
function handleWeaponMount(item: IEntityInstance) {
  state.currentId = item.id
  WeaponMountDialogRef.value.handleShowDialog()
}

/**
 * 显示描述参数对话框
 */
function handleShowDescription(item: IEntityInstance) {
  nextTick(() => {
    state.currentId = item.id
    state.currentTempId = item.basicInfo.entityId
    DescriptionDialogRef.value.handleShowDialog()
  })
}

/**
 * 跟踪实体
 */
function handleTracked(item: IEntityInstance) {
  if (!cesiumStore.customViewer) return

  cesiumStore.customViewer.trackedEntity(item.id)
}

/**
 * 查询控制对象列表
 */
async function handleSearchControlList() {
  try {
    if (scenarioStore.scnId) {
      const { data } = await getSelectedInstanceByScnId(scenarioStore.scnId)
      state.controlList = data
      filterControlObj()
      return Promise.resolve(data)
    }
  } catch (error) {
    return Promise.reject(new Error("查询控制对象失败"))
  }
}

async function handleSearchEntity() {
  try {
    if (scenarioStore.scnId) {
      const { data } = await getSelectedEntityObjectsByScn(scenarioStore.scnId)
      state.list = data
      filterEntity()
      return Promise.resolve(data)
    }
  } catch (error) {
    return Promise.reject(new Error("查询实体失败"))
  }
}

/**
 * 查询阵营列表
 */
async function handleSearchCampList() {
  try {
    const { data } = await getCampList(route.query.id as string)
    state.campList = [{ id: "all", label: "全部" }, ...data]
    if (data.length > 0) {
      scenarioStore.currentSide = data[0]
      state.campId = data[0].id
    }
    return Promise.resolve(true)
  } catch (error) {
    state.campList = [{ id: "all", label: "全部" }]
    return Promise.reject(new Error("查询阵营失败"))
  }
}

function filterEntity() {
  if (state.campId === "all") {
    state.showList = cloneDeep(state.list)
  } else {
    state.showList = state.list.filter(
      item => item.basicInfo.side === state.campId
    )
  }
}

function filterControlObj() {
  if (state.campId === "all") {
    state.showControlList = cloneDeep(state.controlList)
  } else {
    state.showControlList = cloneDeep(
      state.controlList.filter(item => item.side === state.campId)
    )
  }
}

// 初始化实体
function handleInitEntity() {
  // 查询所有实体
  handleSearchEntity().then((list: IEntityInstance[]) => {
    // 绘制实体
    const manager = scenarioStore.drawEntityManager
    if (list && list.length > 0 && manager) {
      list.forEach((item) => {
        manager.initAddEntity(item, (res: IDrawCallback) => {
          item.cesiumId = res.id
          item.cesiumPosition = res.position
          scenarioStore.selectedEntityList.push(
            Object.assign({}, item)
          )
        })
      })
      filterEntity()
    }
  })
}

function handleInitControl() {
  handleSearchControlList().then((list: IControlInstance[]) => {
    // 绘制实体
    const manager = cesiumStore.customViewer?.drawingManager
    if (list && list.length > 0 && manager) {
      list.forEach((item) => {
        manager.initAddDraw(item, (res: IDrawCallback) => {
          item.cesiumId = res.id
          item.cesiumPosition = res.position
          scenarioStore.selectedObjList.push(Object.assign({}, item))
        })
      })
      filterControlObj()
    }
  })
}

function clearAll() {
  const manager = cesiumStore.customViewer?.drawingManager
  scenarioStore.selectedEntityList.forEach((item) => {
    scenarioStore.drawEntityManager?.clearById(item.cesiumId)
  })
  manager?.clearAll()
  return Promise.resolve(true)
}

// 组件挂载时加载数据
onMounted(async () => {
  if (route.query.id) {
    await handleSearchCampList()

    handleInitEntity()
    handleInitControl()

    mitter.on("updateSelectedEntity", () => {
      handleSearchEntity()
    })

    mitter.on("updateSelectedControl", () => {
      handleSearchControlList()
    })
  }
})

onActivated(() => {
  if (scenarioStore.scnId && scenarioStore.scnId !== route.query.id) {
    clearAll()
    handleSearchCampList()
    handleInitEntity()
    handleInitControl()
  }
})

onUnmounted(() => {
  mitter.off("updateSelectedEntity")
  mitter.off("updateSelectedControl")
})
</script>

<template>
  <div class="edit-scenario-selectedlist" :class="{ hidden: selectedListShow }">
    <div class="wrapper">
      <div class="toolbar">
        <span class="title">已选实体</span>
        <el-link :underline="false" @click="handleClose" class="close-btn">
          <el-icon :size="16">
            <Close />
          </el-icon>
        </el-link>
      </div>

      <div class="toolbar function">
        <div class="function_left">
          阵营：
          <el-select
            v-model="campId"
            placeholder="请选择"
            class="select-camp"
            @change="handleChangeCamp"
          >
            <el-option
              v-for="item in campList"
              :key="item.id"
              :label="item.label"
              :value="item.id"
            />
          </el-select>
        </div>

        <div class="right">
          <el-tooltip content="新增阵营" placement="top">
            <el-link :underline="false" type="primary" @click="handleAddCamp">
              <el-icon :size="18">
                <Plus />
              </el-icon>
            </el-link>
          </el-tooltip>
          <el-tooltip content="编辑阵营" placement="top" v-if="campId !== 'all'">
            <el-link :underline="false" type="primary" @click="handlEditCamp">
              <el-icon :size="18">
                <Edit />
              </el-icon>
            </el-link>
          </el-tooltip>
        </div>
      </div>

      <div class="container">
        <el-tabs v-model="activeKey" @tab-click="handleTabChange">
          <el-tab-pane label="实体" name="instance">
            <el-scrollbar>
              <ul class="entity-list" v-if="showList.length > 0">
                <li
                  v-for="item in showList"
                  :key="item.id"
                  class="entity-item"
                >
                  <div class="left" @dblclick="handleTracked(item)">
                    <SvgIcon
                      class="entity-icon"
                      :name="`scenario-${item.entityTypeObj?.kind}-${item.entityTypeObj?.domain}-${item.entityTypeObj?.category}`"
                      :color="item.basicInfo.sideColor"
                    />
                    <span class="title" :title="item.basicInfo.entityName">
                      {{ item.basicInfo.entityName }}
                    </span>
                  </div>
                  <div class="right">
                    <el-tooltip content="编辑属性" placement="top">
                      <el-link :underline="false" @click="handleEntityEdit(item)">
                        <el-icon><Edit /></el-icon>
                      </el-link>
                    </el-tooltip>

                    <el-tooltip content="移动位置" placement="top">
                      <el-link
                        :underline="false"
                        @click="handleInstanceEditVertex(item)"
                      >
                        <el-icon><Rank /></el-icon>
                      </el-link>
                    </el-tooltip>

                    <el-dropdown trigger="hover">
                      <el-link :underline="false">
                        <el-icon><MoreFilled /></el-icon>
                      </el-link>

                      <template #dropdown>
                        <el-dropdown-menu>
                          <el-dropdown-item @click="handleShowDescription(item)">
                            描述参数
                          </el-dropdown-item>
                          <el-dropdown-item @click="handleWeaponMount(item)">
                            武器挂载
                          </el-dropdown-item>
                          <el-dropdown-item @click="handleEntityDelete(item)" class="danger-item">
                            删除
                          </el-dropdown-item>
                        </el-dropdown-menu>
                      </template>
                    </el-dropdown>
                  </div>
                </li>
              </ul>

              <el-empty v-else description="暂无数据" />
            </el-scrollbar>
          </el-tab-pane>

          <el-tab-pane label="控制对象" name="controlObject">
            <el-scrollbar>
              <ul class="entity-list" v-if="showControlList.length > 0">
                <li
                  v-for="item in showControlList"
                  :key="item.id"
                  class="entity-item"
                >
                  <div class="left">
                    <i
                      :class="`iconfont icon-${ControlObjectMap[item.type]} control-icon`"
                      :style="{ color: item.sideColor }"
                    />
                    <span class="title" :title="item.name">
                      {{ item.name }}
                    </span>
                  </div>

                  <div class="right">
                    <el-tooltip content="编辑属性" placement="top">
                      <el-link
                        :underline="false"
                        @click="handleControlEdit(item)"
                      >
                        <el-icon><Edit /></el-icon>
                      </el-link>
                    </el-tooltip>

                    <el-tooltip content="编辑顶点" placement="top">
                      <el-link
                        :underline="false"
                        @click="handleControlEditVertex(item)"
                      >
                        <el-icon><Rank /></el-icon>
                      </el-link>
                    </el-tooltip>

                    <el-dropdown trigger="click">
                      <el-link :underline="false">
                        <el-icon><MoreFilled /></el-icon>
                      </el-link>

                      <template #dropdown>
                        <el-dropdown-menu>
                          <el-dropdown-item @click="handleControlDelete(item)" class="danger-item">
                            删除
                          </el-dropdown-item>
                        </el-dropdown-menu>
                      </template>
                    </el-dropdown>
                  </div>
                </li>
              </ul>

              <el-empty v-else description="暂无数据" />
            </el-scrollbar>
          </el-tab-pane>
        </el-tabs>
      </div>
    </div>

    <WeaponMountDialog ref="WeaponMountDialogRef" v-if="currentId" :id="currentId" />
    <DescriptionDialog ref="DescriptionDialogRef" v-if="currentTempId" :id="currentTempId" />
    <EditCampDialog
      ref="EditCampDialogRef"
      :dialog-type="dialogType"
      :camp-id="campId"
      @update-camp="uplateCampList"
    />
  </div>
</template>

<style lang="scss" scoped>
$toolbar-width: 300px;

.edit-scenario-selectedlist {
  position: absolute;
  height: calc(100%);
  width: $toolbar-width;
  top: 0px;
  left: 0;
  z-index: 999;
  transition: width 0.3s ease;
  background-color: rgba(100, 101, 102, 0.39);
  border-radius: 5px;

  &.hidden {
    width: 0;
    overflow: hidden;
  }

  .wrapper {
    width: 100%;
    height: 100%;
    overflow: hidden;
    display: flex;
    flex-direction: column;
  }

  .container {
    padding: 0 15px 15px 15px;
    height: calc(100% - 67px);
    overflow: hidden;
  }
}

// 头部工具栏
.toolbar {
  padding: var(--main-padding) var(--main-padding) 0 0;
  margin-bottom: 0;
  width: $toolbar-width;
  display: flex;
  align-items: center;
  justify-content: space-between;

  .title {
    &::before {
      display: inline-block;
      height: 21px;
      width: 5px;
      background-color: var(--el-color-primary);
      margin-right: 10px;
      vertical-align: middle;
      content: "";
    }
  }

  .close-btn {
    color: white;

    &:hover {
      color: var(--el-color-primary);
    }
  }

  &.function {
    width: $toolbar-width;
    padding-left: 16px;
    justify-content: space-between;

    .function_left {
      flex: 1;
      display: flex;
      flex-direction: row;
      align-items: center;
    }

    .select-camp {
      margin-right: 5px;
      flex: 1;
    }

    .camp-actions {
      display: flex;
      margin-left: 5px;
    }
  }
}

// 实体列表
.entity-list {
  list-style: none;
  padding: 0 12px 0 0;
  margin: 0;
}

.entity-item {
  display: flex;
  align-items: center;
  justify-content: space-between;
  border-radius: 4px;
  margin-bottom: 4px;
  padding: 8px 12px;
  color: white;

  &:hover {
    background-color: rgba(255, 255, 255, 0.1);
  }

  .left {
    flex: 1;
    display: flex;
    align-items: center;
    overflow: hidden;
    cursor: pointer;

    .entity-icon {
      height: 16px !important;
      width: 16px !important;
      margin-right: 8px;
      flex-shrink: 0;
    }

    .control-icon {
      font-size: 14px;
      margin-right: 8px;
      flex-shrink: 0;
    }

    .title {
      white-space: nowrap;
      overflow: hidden;
      text-overflow: ellipsis;
    }
  }
}

.right {
  display: flex;
  align-items: center;
  gap: 10px;
}

// 按钮样式
.action-btn {
  color: white;
  padding: 4px;

  &:hover {
    color: var(--el-color-primary);
  }
}

.el-tab-pane {
  height: calc(100%);
}

// 标签页样式
:deep(.el-tabs) {
  height: calc(100%);
  color: white;

  .el-tabs__header {
    margin-bottom: 10px;
  }

  .el-tabs__item {
    color: rgba(255, 255, 255, 0.7);

    &.is-active {
      color: white;
    }

    &:hover {
      color: white;
    }
  }

  .el-tabs__active-bar {
    background-color: var(--el-color-primary);
  }
}

// 下拉菜单样式
:deep(.el-dropdown-menu) {
  .danger-item {
    color: var(--el-color-danger);
  }
}

// 空状态样式
:deep(.el-empty) {
  padding: 20px 0;

  .el-empty__description {
    color: rgba(255, 255, 255, 0.7);
  }
}

:deep(.el-select__wrapper) {
  background-color: rgb(234, 238, 251) !important;
}
:deep(.el-select__placeholder) {
  color: #333;
}
</style>
